﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading;
using Azure.Domain.Processors;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using StructureMap;

namespace Worky
{
    public class WorkerRole : RoleEntryPoint
    {
        private IContainer _container;
        private readonly AutoResetEvent _waitHandle = new AutoResetEvent(false);
        private IList<IProcessor> _processors;
        private DiagnosticMonitor _monitor;

        public override void Run()
        {
            // This is a sample worker implementation. Replace with your logic.
            Trace.WriteLine("Worky entry point called", "Information");
            
            _processors = _container.GetAllInstances<IProcessor>();
            foreach (var processor in _processors)
            {
                Trace.WriteLine(String.Format("Starting the processor: {0}", processor.GetType().Name));
                processor.Start();
            }

            _waitHandle.WaitOne();
        }

        protected virtual IContainer BuildContainer()
        {
            IContainer result = new Container(x => x.Scan(y =>
                                                              {
                                                                  y.AssemblyContainingType<IProcessor>();
                                                                  y.WithDefaultConventions();
                                                              }));

            return result;
        }

        public override bool OnStart()
        {
            // Set the maximum number of concurrent connections 
            ServicePointManager.DefaultConnectionLimit = 12;

            _monitor = DiagnosticMonitor.Start("DiagnosticsConnectionString");
            Trace.WriteLine(_monitor.LocalDataDirectory);
            Trace.Listeners.Add(new DiagnosticMonitorTraceListener());
            Trace.AutoFlush = true;

            // For information on handling configuration changes
            // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
            RoleEnvironment.Changing += RoleEnvironmentChanging;

            _container = this.BuildContainer();

            return base.OnStart();
        }

        public override void OnStop()
        {
            _waitHandle.Set();

            foreach (var processor in _processors)
            {
                Trace.WriteLine(String.Format("Starting the processor: {0}", processor.GetType().Name));
                processor.Stop();
                processor.Dispose();
            }

            _processors = null;

            _monitor.Shutdown();
        }

        private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
        {
            // If a configuration setting is changing
            if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange))
            {
                // Set e.Cancel to true to restart this role instance
                e.Cancel = true;
            }
        }
    }
}
